﻿using System.Collections.Generic;
using System.Linq;
using HK.Core.Extend;
using HK.Core.GUIEx.Protocol.Attribute;
using HK.Core.Utils;
using HK.Editor.Common;
using HK.Editor.Common.Protocol;
using HK.Editor.GUIEx.Protocol.Drawer;
using HK.Editor.GUIEx.Protocol.Pagination;
using HK.Editor.Utils;
using UnityEditor;
using UnityEngine;

namespace HK.Editor.GUIEx.Drawer
{
    /// <summary>
    /// GUI绘制器 - 分页面板 - I/O对象
    /// <para>* 文件+文件夹</para>
    /// </summary>
    public class IoPaginationDrawer : StrPaginationDrawer, IIoPaginationDrawer
    {
        
#region Create

        /// <summary>
        /// 创建GUI绘制器 - 分页面板
        /// </summary>
        /// <param name="iList">字符串列表</param>
        /// <param name="iPagination">分页设定</param>
        /// <param name="iBrowseOptions">浏览选项</param>
        /// <param name="iOnAdded">追加回调</param>
        /// <param name="iOnSearched">检索回调</param>
        /// <param name="iSearchBarVisible">检索bar显示标志位</param>
        /// <param name="iDrawFromUnity">是否从Unity调用绘制标志位</param>
        /// <param name="iOptions">选项</param>
        /// <returns>GUI绘制器 - 分页面板</returns>
        public static IIoPaginationDrawer Create(List<string> iList, IPagination iPagination, 
            IOBrowse iBrowseOptions, OnIoAssetsAdded iOnAdded = null, OnSearchBtnClicked iOnSearched = null, 
            bool iDrawFromUnity = false, bool iSearchBarVisible = true, int iOptions = (int)GUIOperateOptions.None)
        {
            return new IoPaginationDrawer(iList, iPagination, iBrowseOptions, iOnAdded, 
                iOnSearched, iDrawFromUnity, iSearchBarVisible, iOptions);
        }

#endregion

        /// <summary>
        /// 保护构造函数
        /// </summary>
        /// <param name="iList">字符串列表</param>
        /// <param name="iPagination">分页设定</param>
        /// <param name="iBrowseOptions">浏览选项</param>
        /// <param name="iOnAdded">追加回调</param>
        /// <param name="iOnSearched">检索回调</param>
        /// <param name="iSearchBarVisible">检索bar显示标志位</param>
        /// <param name="iDrawFromUnity">是否从Unity调用绘制标志位</param>
        /// <param name="iOptions">选项</param>
        private IoPaginationDrawer(List<string> iList, IPagination iPagination, IOBrowse iBrowseOptions,
            OnIoAssetsAdded iOnAdded = null, OnSearchBtnClicked iOnSearched = null, bool iDrawFromUnity = false, 
            bool iSearchBarVisible = true, int iOptions = (int)GUIOperateOptions.None) :
            base(iList, iPagination, iOnSearched, iDrawFromUnity, iOptions)
        {
            BrowseOptions = iBrowseOptions;
            AddElements = iOnAdded;
            SearchBarVisible = iSearchBarVisible;
        }

#region Rect

        /// <summary>
        /// 按钮宽度 - 浏览
        /// </summary>
        private static readonly float _browseBtnWidth = BtnWidthShort;

#endregion

#region Contents
        
        /// <summary>
        /// 按钮 - 浏览
        /// </summary>
        protected GUIContent BrowseBtnContent { get; private set; } = null;

        /// <summary>
        /// 初始化GUIContent
        /// </summary>
        protected override void InitContents()
        {
            base.InitContents();
            
            // 浏览按钮
            BrowseBtnContent = UtilsGUIEx.CreateGuiContentWithIcon("浏览", EditorConst.IconBrowse);
        }

        /// <summary>
        /// 取得Element标题
        /// </summary>
        /// <param name="iIndex">Element索引</param>
        /// <param name="iStr">字符串</param>
        /// <returns>Element标题</returns>
        protected override GUIContent GetElementCaption(int iIndex, string iStr)
        {
            GUIContent caption = null;
            if (!ElementsCaptions.TryGetValue(iIndex, out caption))
            {
                caption = UtilsGUIEx.CreateGuiContentByPathOfAsset(iStr, iStr, true, false);
                caption.text = $"({iIndex}){caption.text}";
                ElementsCaptions.Add(iIndex, caption);
            }
            else
            {
                if (null == caption)
                {
                    caption = UtilsGUIEx.CreateGuiContentByPathOfAsset(iStr, iStr, true, false);
                    caption.text = $"({iIndex}){caption.text}";
                }
                ElementsCaptions[iIndex] = caption;
            }
                    
            return caption;
        }

#endregion

#region Browse
        
        /// <summary>
        /// 浏览选项
        /// </summary>
        public IOBrowse BrowseOptions { get; private set; } = null;

        /// <summary>
        /// 追加回调
        /// </summary>
        public OnIoAssetsAdded AddElements { get; private set; } = null;

#endregion

#region Events

        /// <summary>
        /// 删除Element按钮点击时间
        /// </summary>
        private void OnDelElementBtnClicked(object iArgs) => OnDelElementBtnClicked();

        /// <summary>
        /// 委托定义 : 文件/文件夹拖拽
        /// </summary>
        /// <param name="iAssets">拖拽的资产列表(如:文件/文件夹等)</param>
        protected override void OnAssetsDragAndDropDown(string[] iAssets)
        {
            var assets = iAssets;
            if(null == iAssets || 0 >= iAssets.Length) return;

            var assetKeys = new List<string>();
            var count = assets.Length;
            for (var idx = 0; idx < count; ++idx)
            {
                var asset = assets[idx];
                if(string.IsNullOrEmpty(asset)) continue;
                        
                if(!UtilsIo.IsAssetPath(asset, out var oAssetPath)) continue;
                assetKeys.Add(oAssetPath);
            }

            assetKeys = assetKeys.Distinct().ToList();
            if(0 >= assetKeys.Count) return;

            var addedCount = 0;
            if (null == AddElements)
            {
                var aCount = assetKeys.Count;
                for (var idx = 0; idx < aCount; ++idx)
                {
                    var assetKey = assetKeys[idx];
                    if(string.IsNullOrEmpty(assetKey)) continue;
                
                    if (0 >= List.Count)
                    {
                        List.Add(assetKey);
                        addedCount = 1;
                    }
                    else
                    {
                        if (!List.Exists(iO => iO.Equals(assetKey)))
                        {
                            List.Add(assetKey);
                            ++addedCount;
                        }
                    }
                }
            }
            else
            {
                addedCount = AddElements.Invoke(assetKeys);
            }       
            
            // 重绘
            if (0 >= addedCount)
            {
                RefreshElementCaptions();
                HandleUtility.Repaint();
            }
        }

#region Menu

        /// <summary>
        /// 显示Element选中鼠标右键菜单
        /// </summary>
        /// <param name="iElement">Element</param>
        private void ShowElementRightClickMenu(string iElement)
        {
            var curIndex = IndexOf(iElement);
            if (ListSelection.Select(curIndex))
            {
                HandleUtility.Repaint();
            }

            if (Searching)
            {
                var searchCapsule = SearchResult[curIndex];
                curIndex = searchCapsule.Index;
            }
            
            var menu = new GenericMenu();

            // 删除按钮
            if (Removable)
            {
                menu.AddItem(UtilsGUIEx.CreateGuiContent("删除"), false, OnDelElementBtnClicked, curIndex);
            }
            
            menu.ShowAsContext();
        }

#endregion

#endregion

#region Draw

        /// <summary>
        /// 绘制Element
        /// </summary>
        /// <param name="iRect">绘制矩形区域</param>
        /// <param name="iEvent">Event</param>
        /// <param name="iElementIndex">Element索引</param>
        /// <param name="iElementCaption">Element标题</param>
        /// <param name="iElementValue">Element值</param>
        /// <param name="iSelected">选中标志位</param>
        /// <param name="iFocused">焦点</param>
        /// <returns>绘制范围</returns>
        protected override Rect DrawElement(Rect iRect, Event iEvent, int iElementIndex, 
            GUIContent iElementCaption, string iElementValue, bool iSelected, bool iFocused)
        {
            var displayRect = iRect;
            
            // 可选中背景
            var bgRect = displayRect;
            var selectBgRect = displayRect;
            selectBgRect.xMin += HorizontalSpacing;
            selectBgRect.yMax += 1;
            selectBgRect = UtilsGUIEx.DrawListElementBg(selectBgRect, iEvent, iSelected, iFocused);
            
            var dragMarkRect = displayRect;
            dragMarkRect.y = displayRect.yMin + VerticalSpacing;
            dragMarkRect.width = DragMarkWidth;
            dragMarkRect = UtilsGUIEx.DrawDragMark(dragMarkRect, iEvent);

            var captionLabelBgRect = bgRect;
            captionLabelBgRect.xMin = dragMarkRect.xMax + HorizontalSpacing;
            captionLabelBgRect.xMax -= (HorizontalSpacing + _browseBtnWidth + 1);
            captionLabelBgRect.yMin += 1;
            captionLabelBgRect.yMax -= 1;
            captionLabelBgRect = UtilsGUIEx.DrawIoTargetBg(captionLabelBgRect, iEvent, false, false);

            var captionLabelRect = captionLabelBgRect;
            captionLabelRect.xMin += HorizontalSpacing;
            captionLabelRect.xMax -= HorizontalSpacing;
            EditorGUI.LabelField(captionLabelRect, iElementCaption);
            
            var browseBtnRect = captionLabelBgRect;
            browseBtnRect.xMin = captionLabelBgRect.xMax;
            browseBtnRect.xMax = bgRect.xMax - HorizontalSpacing;
            browseBtnRect = UtilsGUIEx.DrawBrowseButton(browseBtnRect, iEvent, iElementValue,
                (iAssetPath) =>
                {
                    OnAssetsDragAndDropDown(new[] { iAssetPath });
                }, BrowseOptions.FileBrowseOnly, BrowseOptions.BrowseDesc, BrowseOptions.BrowseExtensions);

            var elementControlId = GetElementControlId(iElementIndex);
            if (-1 != elementControlId)
            {
                // 挂接事件
                HandleMouseEvents(displayRect, iEvent, elementControlId, 
                    (iControlId) =>
                    {
                        var targetIndex = GetElementIndexByControlId(iControlId);
                        ListSelection.Select(targetIndex);

                        var targetValue = GetElementValue(targetIndex);
                        UtilsGUIEx.PingAsset(targetValue);
                    }, (iControlId) =>
                    {
                        var targetIndex = GetElementIndexByControlId(iControlId);
                        var targetValue = GetElementValue(targetIndex);
                        ShowElementRightClickMenu(targetValue);
                    });
            }
            
            return displayRect;
        }

#endregion
        
    }
}
